#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <pthread.h>
#include <arpa/inet.h>

#include "pack.h"
#include "main.h"

extern unsigned int filenum;
extern unsigned int sendfilenum;
extern long baonum;
extern char VERSION[20];
extern char USER[5];
extern char COMPUTER[20];
extern char NAME[10];
extern char GROUP[15];
extern char PHONE[15];
extern char EMAIL[15];
extern char IP[20];
extern char MAC[20];
extern char SIGN[20];
extern struct TransFile rFiles[10];
extern struct TransFile sFiles[10];
extern FEIGE_REQ *head;


int packdata(char *buf,int n)//1025 广播包
{
	int bufsize = 0;
	int len;
	memset(buf,0,n);

	baonum ++;
	bufsize = sprintf(buf,"%s:%lu:%s:%s:1025:",VERSION,baonum,USER,COMPUTER);
	len = sprintf(buf+bufsize,"%s%c%s%c%s%c%c%s%c%s%c%c5%c",
		   		  NAME,0,GROUP,0,MAC,0,0,PHONE,0,EMAIL,0,0,0);
	bufsize += len;
	len = sprintf(buf+bufsize,"%s%c%c15%c10000001%c%s%c%s",
			      IP,0,0,0,0,SIGN,0,COMPUTER);
	bufsize += len;
	return bufsize;
}

int packdata_sure(char *buf,int n)//3 确认包
{
	int bufsize = 0;
	int len;
	memset(buf,0,n);

	baonum ++;
	bufsize = sprintf(buf,"%s:%lu:%s:%s:3:",VERSION,baonum,USER,COMPUTER);
	len = sprintf(buf+bufsize,"%s%c%s%c%s%c%c%s%c%s%c%c5%c",
		   		  NAME,0,GROUP,0,MAC,0,0,PHONE,0,EMAIL,0,0,0);
	bufsize += len;
	len = sprintf(buf+bufsize,"%s%c%c15%c10000001%c%s%c%s",
			      IP,0,0,0,0,SIGN,0,COMPUTER);
	bufsize += len;
	return bufsize;
}

int data_8e(char *buf,FEIGE_REQ *pnew,int n)//判断是否为8E包，返回33包
{
	int size;
	baonum++;
	memset(buf,0,n);
	size = sprintf(buf,"%s:%lu:%s:%s:33:%s",VERSION,baonum,USER,COMPUTER,pnew->seq);
	return size;
}

int data_e7(char *buf,FEIGE_REQ *pnew,int n)//打开聊天窗口，发送487包，写入对方mac地址
{
	int size;
	baonum++;
	memset(buf,0,n);
	size = sprintf(buf,"%s:%lu:%s:%s:487:%s",VERSION,baonum,USER,COMPUTER,pnew->mac);
	return size;
}


int data_288(char *buf,char *newsend,int n)//发送聊天信息，发送288包
{
	int size;
	baonum++;
	memset(buf,0,n);
	size = sprintf(buf,"%s:%lu:%s:%s:288:%s[rich]0A0000000000860008AE5F6F8FC596D19E12000000000000000000000000000000000000[/rich]",VERSION,baonum,USER,COMPUTER,newsend);
	return size;
}

int data_96(char *buf,FEIGE_REQ *pnew,int n)//组96包
{
	int size;
	char seqbuf[20] = {0},seq_1buf[20] = {0};
	unsigned int seq,seq_1;
	sscanf(pnew->seq,"%d",&seq);
	seq_1 = seq-1;
	//printf("seq:%x,seq_1:%x\n",seq,seq_1);
	sprintf(seqbuf,"%x",seq);
	sprintf(seq_1buf,"%x",seq_1);
	baonum++;
	memset(buf,0,n);
	size = sprintf(buf,"1.1.180210:%lu:%s:%s:96:%s:%s:0:",baonum,USER,COMPUTER,seqbuf,seq_1buf);
	return size;
}

int jie_96(char *pktnum,char *buf,int n)//解96包
{
	//printf("buf:%s\n",buf);
	char *p = NULL;
	unsigned int t;
	memset(pktnum,0,n);
	if((p = strchr(buf,':')))//version
	{
		buf = p+1;//6
	}
	if((p = strchr(buf,':')))//接收方自己的包编号
	{
		buf = p+1;//l
	}
	if((p = strchr(buf,':')))//jiehsoufang de user
	{
		buf = p+1;//L
	}
	if((p = strchr(buf,':')))//接收方自己的host
	{
		buf = p+1;
	}
	if((p = strchr(buf,':')))//96
	{
		buf = p+1;
	}
	if((p = strchr(buf,':')))//要接收文件的包编号
	{
		*p = '\0';
		//printf("%s\n",buf);
		sscanf(buf,"%x",&t);
		//printf("shi:%x\n",t);
		sprintf(pktnum,"%d",t);
		//printf("shizifu:%s\n",pktnum);
	}
	return 0;
}

int pack_2097440(char *buf,struct stat *st,char *newsend,char *name,int n)//组2097440包
{
	memset(buf,0,n);
	baonum += 2;
	char atime[20] = {0};
    int size = sprintf(buf, "%s:%lu:%s:%s:%s:%c%lu:%s:%lx:0:1:%lu:%lu:%lu:%lc"
                ,"5.1.141114",baonum,USER,COMPUTER,
                "2097440",0,baonum-1,newsend, st->st_size, st->st_ctime, st->st_mtime, st->st_atime, 0);
    //*sq = baonum+1;
    //printf("filename:%s\n",newsend);
    //printf("filesize:%lx\n",st->st_size);
    //printf("atime:%lu\n",st->st_atime);
    int i;
    char baoseq[20] = {0};
	//char *p = NULL;
	FEIGE_REQ *pb = head->next;
	//printf("jinru?:%s\n",buf);
	sendfilenum++;
	if(sendfilenum == 10)
	{
		perror("too many file\n");
		return 0;
	}
	for(i=0;i<10;i++)
	{
		if(sFiles[i].fileid == 0)
		{
			sprintf(baoseq,"%lu",baonum);
			strcpy(sFiles[i].pktid,baoseq);
			sFiles[i].fileid = sendfilenum;
			strcpy(sFiles[i].filename,newsend);

			sFiles[i].offset = 0;
			sFiles[i].filesize = st->st_size;
			sFiles[i].status = 0;
			sprintf(atime,"%lu",st->st_atime);
			strcpy(sFiles[i].starttime,atime);
			while(pb)
			{
				if(strcmp(pb->name,name) == 0)
				{
					strcpy(sFiles[i].perrip,pb->ip);
					//printf("ip:%s\n",pb->ip);
					break;
				}
				pb = pb->next;
			}
		}
		break;
	}

    return size;
}

FEIGE_REQ *jiexibao(char *recvbuf)//传入别人的上线包，解析包，将上线的用户属性加入链表
{
	//char *recv = recvbuf;
	char *p = NULL;
	FEIGE_REQ *pnew = NULL;

	pnew = (FEIGE_REQ *)malloc(sizeof(FEIGE_REQ));

	if((p = strchr(recvbuf,':')) != NULL)
	{
		*p = '\0';
		strcpy(pnew->version,recvbuf);
		//printf("version=%s\n",pnew->version);
		recvbuf = p + 1;
	}
	if((p = strchr(recvbuf,':')) != NULL)
	{
		*p = '\0';
		strcpy(pnew->seq,recvbuf);
		//printf("seq=%s\n",pnew->seq);
		recvbuf = p + 1;	
	}
	if((p = strchr(recvbuf,':')) != NULL)
	{
		*p = '\0';
		//printf("user=%s\n",recvbuf);
		strcpy(pnew->user,recvbuf);
		recvbuf = p + 1;	
	}
	if((p = strchr(recvbuf,':')) != NULL)
	{
		*p = '\0';
		//printf("host=%s\n",recvbuf);
		strcpy(pnew->host,recvbuf);
		recvbuf = p + 1;
	}
	if((p = strchr(recvbuf,':')) != NULL)
	{
		*p = '\0';
		//printf("%d\n",atoi(recvbuf));
		pnew->cmd = atoi(recvbuf);
		//printf("%d\n",pnew->cmd);
		recvbuf = p + 1;
	}
	if((p = strchr(recvbuf,'\0')) != NULL)
	{
		//*p = '\0';
		//printf("nichen=%s\n",recvbuf);
		strcpy(pnew->name,recvbuf);
		recvbuf = p + 1;
	}
	if((p = strchr(recvbuf,'\0')) != NULL)
	{
		//*p = '\0';
		//printf("qunzu=%s\n",recvbuf);
		strcpy(pnew->group,recvbuf);
		recvbuf = p + 1;
	}
	if((p = strchr(recvbuf,'\0')) != NULL)
	{
		//*p = '\0';
		//printf("mac=%s\n",recvbuf);
		strcpy(pnew->mac,recvbuf);
		recvbuf = p + 2;
	}
	if((p = strchr(recvbuf,'\0')) != NULL)
	{
		//*p = '\0';
		//printf("phone=%s\n",recvbuf);
		strcpy(pnew->phone,recvbuf);
		recvbuf = p + 1;
	}
	if((p = strchr(recvbuf,'\0')) != NULL)
	{
		//*p = '\0';
		//printf("email=%s\n",recvbuf);
		strcpy(pnew->email,recvbuf);
		recvbuf = p + 4;
	}
	if((p = strchr(recvbuf,'\0')) != NULL)
	{
		//*p = '\0';
		//printf("ip=%s\n",recvbuf);
		strcpy(pnew->ip,recvbuf);
		//printf("%s\n",pnew->ip);
		recvbuf = p + 2;
	}
	if((p = strchr(recvbuf,'\0')) != NULL)
	{
		//*p = '\0';
		//printf("touxiang=%s\n",recvbuf);
		recvbuf = p + 10;
	}
	if((p = strchr(recvbuf,'\0')) != NULL)
	{
		//*p = '\0';
		//printf("qianming=%s\n",recvbuf);
		strcpy(pnew->sign,recvbuf);
		//printf("%s\n",pnew->sign);
	}
	pnew->next = NULL;
	return pnew;
}


int test_ip(FEIGE_REQ *pnew)//检测上线的用户是否已经写入链表，看昵称是否更改
{
	FEIGE_REQ *p = NULL,*pb = NULL;
	p = head;
	while(p != NULL)
	{
		if(strcmp(p->ip,pnew->ip) == 0)
			break;
		pb = p;
		p = p->next;
	}
	if(p == NULL)
	{
		pb->next = pnew;
		//printf("ipppppppp:%s\n",pb->next->ip);
		//printf("nameeeeee:%s\n",pnew->name);
	}
	else if(p != NULL)
	{
		if(strcmp(p->name,pnew->name))
			strcpy(p->name,pnew->name);
	}
	return 0;
}

int send_message(char *name,char *newsend)//发送消息
{
	int sock = socket(AF_INET,SOCK_DGRAM,0);
	int opt = 1;
	if(setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)))
	{
		perror("setsockopt error\n");
	}
	struct sockaddr_in send_addr;
	int send_len = sizeof(send_addr);
	char buf[1024] = {0};
	int size;
	FEIGE_REQ *new = NULL;
	new = head->next;
	while(new)
	{
		if(!strcmp(new->name,name))
			break;
		new = new->next;
	}
	if(new)
	{
		send_addr.sin_family = AF_INET;
		send_addr.sin_port = htons(2425);
		inet_pton(AF_INET,new->ip,&send_addr.sin_addr.s_addr);
		size = data_e7(buf,new,1024);
		sendto(sock,buf,size,0,(struct sockaddr *)&send_addr,send_len);
		sleep(1);
		size = data_288(buf,newsend,1024);
		sendto(sock,buf,size,0,(struct sockaddr *)&send_addr,send_len);
	}
	return 0;
}


int data_2097440(FEIGE_REQ *pnew)//解析2097400包   
{
	int i;
	char *buf = NULL,*p = NULL;
	FEIGE_REQ *pb = head->next;
	buf = pnew->group;
	//printf("jinru?:%s\n",buf);
	filenum++;
	if(filenum == 10)
	{
		perror("too many file\n");
		return 0;
	}
	for(i=0;i<10;i++)
	{
		if(rFiles[i].fileid == 0)
		{
			strcpy(rFiles[i].pktid,pnew->seq);
			rFiles[i].fileid = filenum;
			if((p = strchr(buf,':'))) //seq -1
			{
				*p = '\0';
				//printf("///////%s\n",buf);
				buf = p + 1;
			}
			if((p = strchr(buf,':'))) //filename
			{
				*p = '\0';
				strcpy(rFiles[i].filename,buf);
				//printf("filename:%s\n",buf);
				buf = p + 1;
			}
			if((p = strchr(buf,':')))  //filesize
			{
				*p = '\0';
				sscanf(buf,"%x",&rFiles[i].filesize);
				//printf("filesize:%d\n",rFiles[i].filesize);
				buf = p + 1;
			}
			if((p = strchr(buf,':'))) //0
			{
				*p = '\0';
				//printf("%s\n",buf);
				buf = p + 1;
			}
			if((p = strchr(buf,':')))  //1
			{
				*p = '\0';
				//printf("%s\n",buf);
				buf = p + 1;
			}
			if((p = strchr(buf,':'))) //ctime
			{
				*p = '\0';
				//printf("%s\n",buf);
				buf = p + 1;
			}
			if((p = strchr(buf,':')))  //mtime
			{
				*p = '\0';
				//printf("%s\n",buf);
				buf = p + 1;
			}
			if((p = strchr(buf,':')))  //atime
			{
				*p = '\0';
				strcpy(rFiles[i].starttime,buf);
				//printf("atime:%s\n",buf);
			}
			rFiles[i].offset = 0;
			rFiles[i].status = 0;
			while(pb)
			{
				if(strcmp(pb->user,pnew->user) == 0)
				{
					strcpy(rFiles[i].perrip,pb->ip);
					//printf("ip:%s\n",pb->ip);
					break;
				}
				pb = pb->next;
			}
		}
		break;
	}

}

void *tcp_client(void *arg)//创建客户端，发送96包，接收文件
{
	FEIGE_REQ *p = (FEIGE_REQ *)arg;
	int sock,ret,i,size;
	FILE *fp;
	//FEIGE_REQ *pb = head->next;
	char ip[20] = {0},buf[1024] = {0},filename[20] = {0};
	
	struct sockaddr_in addr;
	sock = socket(AF_INET,SOCK_STREAM,0);
	if(sock == -1)
	{
		perror("sock error\n");
		return 0;
	}
	addr.sin_family = AF_INET;
	addr.sin_port = htons(2425);
	for(i=0;i<10;i++)
	{
		if(strcmp(rFiles[i].pktid,p->seq) == 0)
		{
			strcpy(ip,rFiles[i].perrip);
			strcpy(filename,rFiles[i].filename);
		}
		break;
	}
	inet_pton(AF_INET,ip,&addr.sin_addr.s_addr);
	ret = connect(sock,(struct sockaddr *)&addr,sizeof(addr));
	if(ret == -1)
	{
		perror("connect error\n");
		return 0;
	}

	size = data_96(buf,p,1024);
	send(sock,buf,size,0);
	if(access(filename,F_OK) != 0)
	{
		creat(filename,0666);
	}
	fp = fopen(filename,"a");
	if(fp == NULL)
	{
		perror("open file error\n");
		return 0;
	}
	memset(buf,0,sizeof(buf));
	while(recv(sock,buf,sizeof(buf),0) > 0)
	{
		fprintf(fp,"%s",buf);
		memset(buf,0,sizeof(buf));
	}
	fclose(fp);
	return NULL;
}

void *udp_login(void *arg)//自己上线发送1025 udp 广播包
{
	//pthread_detach(pthread_self());
	int sock;
	int bufsize;
	char buf[200] = {0};
	//ENV *head = read_env();

	sock = socket(AF_INET,SOCK_DGRAM,0);
	struct sockaddr_in addr;
	addr.sin_family = AF_INET;
	addr.sin_port = htons(2425);
	inet_pton(AF_INET,"192.168.186.255",&addr.sin_addr.s_addr);

	int opt = 1;
	if(setsockopt(sock,SOL_SOCKET,SO_BROADCAST,&opt,sizeof(opt)) != 0)
	{
		perror("setsockopt error");
		return 0;
	}
	while(1)
	{
		bufsize = packdata(buf,200);
		sendto(sock,buf,bufsize,0,(struct sockaddr *)&addr,sizeof(addr));
		memset(buf,0,sizeof(buf));
		sleep(5);
	}
	close(sock);
	return NULL;
}

void *udp_otherlogin(void *arg)//接收别人上线...信息，并做出判断，返回什么包
{
	pthread_detach(pthread_self());
	pthread_t tid;
	int sock;
	FEIGE_REQ *pnew = NULL;
	char buf[200] = {0};
	char sndbuf[200] = {0};
	char user[20] = {0},chatbuf[200] = {0},*p = NULL;
	int ret,ret2;
	int size;
	sock = socket(AF_INET,SOCK_DGRAM,0);
	struct sockaddr_in addr;
	addr.sin_family = AF_INET;
	addr.sin_port = htons(2425);
	addr.sin_addr.s_addr  = INADDR_ANY;

	if(bind(sock,(struct sockaddr*)&addr,sizeof(addr)) < 0)
	{
		perror("bind error");
		return 0;
	}

	struct sockaddr_in caddr;
	unsigned int len = sizeof(caddr);

	int opt = 1;
	if(setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)) != 0)
	{
		perror("setsockopt error");
	}
	while((ret = recvfrom(sock,buf,sizeof(buf),0,(struct sockaddr*)&caddr,&len)) >= 0)
	{
		pnew = jiexibao(buf);
		if((pnew->cmd == 1025) && strcmp(pnew->ip,IP))
		{
			ret2 = packdata_sure(sndbuf,200);
			sendto(sock,sndbuf,ret2,0,(struct sockaddr*)&caddr,len);
			test_ip(pnew);
		}
		else if(pnew->cmd == 3)
		{
			if(strcmp(pnew->ip,IP))
			{
				test_ip(pnew);
			}
		}
		else if((pnew->cmd == 2147484026) || (pnew->cmd == 487))
		{
			size = data_8e(buf,pnew,200);
			sendto(sock,buf,size,0,(struct sockaddr *)&caddr,len);
		}
		else if(pnew->cmd == 288)
		{
			size = data_8e(buf,pnew,200);
			sendto(sock,buf,size,0,(struct sockaddr *)&caddr,len);
			//char user[20],chatbuf[200],*p;
			strcpy(user,pnew->user);
			strcpy(chatbuf,pnew->name);
			p = strchr(chatbuf,'[');
			*p = '\0';

			//添加一步：用户名是否存在
			FEIGE_REQ *new = NULL;
			new = head->next;
			while(new)
			{
				if(strcmp(new->user,user) == 0)
					break;
				new = new->next;
			}
			if(new)
			{
				printf("[%s]%s:%s\n",new->ip,new->name,chatbuf);
			}
		}
		else if(pnew->cmd == 2097440)
		{
			//printf("bufff:%s\n",pnew->group);	//文件名等信息放在group中	
			size = data_8e(buf,pnew,200);
			sendto(sock,buf,size,0,(struct sockaddr *)&caddr,len);
			data_2097440(pnew);
			pthread_create(&tid,NULL,tcp_client,pnew);
		}
		memset(buf,0,sizeof(buf));
		memset(sndbuf,0,sizeof(sndbuf));
		memset(user,0,sizeof(user));
		memset(chatbuf,0,sizeof(chatbuf));
		p = NULL;
	}
	close(sock);
	return NULL;
}